package plugin_manager

import (
	"context"
	"errors"
	"fmt"
	"log"
	"math"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/sync/semaphore"
	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/credentials"

	"device-modbus/internal/biz/model"
	"device-modbus/internal/biz/query"
	"device-modbus/plugin"
)

// 常量定义
const (
	// 默认并发限制
	defaultMaxConnWorkers  = 5  // 连接并发数
	defaultMaxHeartWorkers = 10 // 心跳并发数

	// 默认超时设置
	defaultDialTimeout      = 5 * time.Second // gRPC拨号超时
	defaultInitTimeout      = 3 * time.Second // 插件初始化超时
	defaultHeartbeatTimeout = 3 * time.Second // 心跳请求超时
	defaultRequestTimeout   = 3 * time.Second // 业务请求超时
	defaultCloseTimeout     = 2 * time.Second // 连接关闭超时

	// 健康检查核心配置
	maxFailedHeartbeats  = 3                // 最大连续失败心跳次数
	defaultHeartbeatFreq = 5 * time.Second  // 主动心跳检查频率（核心轮询间隔）
	defaultCheckInterval = 30 * time.Second // 连接状态检查间隔
	heartbeatSendTimeout = 3                // 心跳发送超时倍数（心跳频率的倍数）
)

// 配置选项
type Options struct {
	CheckInterval   time.Duration // 连接检查间隔
	HeartbeatFreq   time.Duration // 主动心跳频率（核心轮询参数）
	MaxConnWorkers  int64         // 最大连接并发数
	MaxHeartWorkers int64         // 最大心跳并发数
	TLSConfig       TLSConfig     // TLS配置
	Logger          *log.Logger   // 自定义日志
	EnableMetrics   bool          // 是否启用指标收集
}

// TLS配置
type TLSConfig struct {
	Enabled    bool
	CertFile   string
	ServerName string
}

// 插件连接信息
type PluginConn struct {
	Client            plugin.PluginServiceClient
	Conn              *grpc.ClientConn
	ProtocolName      string
	DeviceAddr        string
	Meta              *plugin.PluginMeta
	LastActive        atomic.Int64 // 最后活动时间（毫秒）
	LastHeartbeat     atomic.Int64 // 最后心跳成功时间（毫秒）
	LastHeartbeatSent atomic.Int64 // 最后发送心跳时间（毫秒，无论成功与否）
	FailedHeartbeats  atomic.Int32 // 连续失败心跳次数
}

// 插件管理器
type PluginManager struct {
	connMap       map[string]*PluginConn // 插件连接映射（key:插件名称）
	mu            sync.RWMutex           // 读写锁（并发安全）
	ticker        *time.Ticker           // 主监控定时器（连接检查+心跳）
	checkInterval time.Duration          // 连接检查间隔
	heartbeatFreq time.Duration          // 主动心跳频率（核心轮询）
	connSemaphore *semaphore.Weighted    // 连接并发信号量
	heartbeatSem  *semaphore.Weighted    // 心跳并发信号量
	stopCtx       context.Context        // 停止信号上下文
	stopCancel    context.CancelFunc     // 停止信号触发器
	tlsConfig     TLSConfig              // TLS配置
	logger        *log.Logger            // 日志实例
	wg            sync.WaitGroup         // 协程等待组
	metrics       *metricsCollector      // 指标收集器
	running       atomic.Bool            // 运行状态
}

// 指标收集器（原子操作保证并发安全）
type metricsCollector struct {
	totalConnections   atomic.Int64 // 总连接次数
	activeConnections  atomic.Int64 // 当前活跃连接数
	failedConnections  atomic.Int64 // 失败连接数
	heartbeatSuccesses atomic.Int64 // 心跳成功次数
	heartbeatFailures  atomic.Int64 // 心跳失败次数
	heartbeatSent      atomic.Int64 // 心跳发送总数
	requestSuccesses   atomic.Int64 // 业务请求成功次数
	requestFailures    atomic.Int64 // 业务请求失败次数
}

// 新建插件管理器（初始化所有依赖和配置）
func NewPluginManager(opts Options) (*PluginManager, error) {
	// 设置默认配置
	if opts.CheckInterval <= 0 {
		opts.CheckInterval = defaultCheckInterval
	}
	if opts.HeartbeatFreq <= 0 {
		opts.HeartbeatFreq = defaultHeartbeatFreq
	}
	if opts.MaxConnWorkers <= 0 {
		opts.MaxConnWorkers = defaultMaxConnWorkers
	}
	if opts.MaxHeartWorkers <= 0 {
		opts.MaxHeartWorkers = defaultMaxHeartWorkers
	}
	if opts.Logger == nil {
		opts.Logger = log.Default()
	}

	// 验证TLS配置
	if opts.TLSConfig.Enabled && opts.TLSConfig.CertFile == "" {
		return nil, errors.New("TLS启用但未提供证书文件（CertFile）")
	}

	// 初始化核心组件
	stopCtx, stopCancel := context.WithCancel(context.Background())
	m := &PluginManager{
		connMap:       make(map[string]*PluginConn),
		checkInterval: opts.CheckInterval,
		heartbeatFreq: opts.HeartbeatFreq,
		connSemaphore: semaphore.NewWeighted(opts.MaxConnWorkers),
		heartbeatSem:  semaphore.NewWeighted(opts.MaxHeartWorkers),
		stopCtx:       stopCtx,
		stopCancel:    stopCancel,
		tlsConfig:     opts.TLSConfig,
		logger:        opts.Logger,
		ticker:        time.NewTicker(opts.CheckInterval),
	}

	// 初始化指标收集器
	if opts.EnableMetrics {
		m.metrics = &metricsCollector{}
	}

	return m, nil
}

// 启动管理器（启动监控协程）
func (m *PluginManager) Start() error {
	if !m.running.CompareAndSwap(false, true) {
		return errors.New("插件管理器已启动，请勿重复调用")
	}

	// 启动监控协程（连接检查+主动心跳）
	m.wg.Add(1)
	go m.monitoringLoop()

	m.logger.Printf("插件管理器启动成功（主动心跳频率: %v）", m.heartbeatFreq)
	return nil
}

// 监控循环（核心逻辑：连接检查+主动心跳轮询）
func (m *PluginManager) monitoringLoop() {
	defer m.wg.Done()
	defer m.running.Store(false)
	m.logger.Println("监控循环已启动（含主动心跳轮询）")

	// 初始检查（立即执行一次）
	m.checkAndUpdateConnections()
	m.sendHeartbeats()

	// 定时循环执行
	for {
		select {
		case <-m.stopCtx.Done():
			m.logger.Println("监控循环收到关闭信号，退出")
			return
		case <-m.ticker.C:
			// 并行执行连接检查和主动心跳
			var wg sync.WaitGroup
			wg.Add(2)
			go func() { defer wg.Done(); m.safeExecute(m.checkAndUpdateConnections) }()
			go func() { defer wg.Done(); m.safeExecute(m.sendHeartbeats) }()
			wg.Wait()
		}
	}
}

// 安全执行函数（捕获panic，避免单个任务崩溃整个协程）
func (m *PluginManager) safeExecute(fn func()) {
	defer func() {
		if r := recover(); r != nil {
			m.logger.Printf("任务执行异常（已恢复）: %v", r)
		}
	}()
	fn()
}

// 检查并更新所有插件连接（新增/重连/清理）
func (m *PluginManager) checkAndUpdateConnections() {
	m.logger.Println("开始检查插件连接状态")

	// 查询启用的插件
	enabledPlugins, err := m.queryEnabledPlugins()
	if err != nil {
		m.logger.Printf("查询启用插件失败: %v", err)
		return
	}

	// 无启用插件时清理所有连接
	if len(enabledPlugins) == 0 {
		m.logger.Println("无启用插件，清理所有连接")
		m.cleanupAllConnections()
		return
	}

	// 构建启用插件映射（优化查询效率）
	enabledMap := make(map[string]*model.DeviceAgreement, len(enabledPlugins))
	for _, p := range enabledPlugins {
		enabledMap[p.Name] = p
	}

	// 并发处理每个插件连接
	var wg sync.WaitGroup
	for name, pluginInfo := range enabledMap {
		wg.Add(1)
		go func(name string, info *model.DeviceAgreement) {
			defer wg.Done()
			m.processPluginConnection(name, info)
		}(name, pluginInfo)
	}
	wg.Wait()

	// 清理已禁用的插件连接
	m.cleanupDisabledPlugins(enabledMap)

	// 更新活跃连接数指标
	if m.metrics != nil {
		m.metrics.activeConnections.Store(int64(len(m.connMap)))
	}
}

// 处理单个插件的连接（创建/重连逻辑）
func (m *PluginManager) processPluginConnection(name string, info *model.DeviceAgreement) {
	// 读锁检查现有连接
	m.mu.RLock()
	existingConn, exists := m.connMap[name]
	currentAddr := info.DeviceAddr
	m.mu.RUnlock()

	// 判断是否需要新建连接
	needsNewConn, reason := m.needNewConnection(exists, existingConn, currentAddr)
	if !needsNewConn {
		// 连接有效，更新活动时间
		existingConn.LastActive.Store(time.Now().UnixMilli())
		m.logger.Printf("插件连接有效: %s（地址：%s）", name, currentAddr)
		return
	}

	m.logger.Printf("插件需新建连接: %s，原因：%s", name, reason)

	// 申请连接信号量（控制并发）
	if err := m.connSemaphore.Acquire(m.stopCtx, 1); err != nil {
		m.logger.Printf("获取连接信号量失败（%s）: %v", name, err)
		return
	}
	defer m.connSemaphore.Release(1)

	// 带重试创建连接
	newConn, meta, err := m.createPluginConnectionWithRetry(name, currentAddr, 2)
	if err != nil {
		m.logger.Printf("创建插件连接失败（%s@%s）: %v", name, currentAddr, err)
		if m.metrics != nil {
			m.metrics.failedConnections.Add(1)
		}
		return
	}

	// 写锁更新连接映射
	m.mu.Lock()
	defer m.mu.Unlock()

	// 二次检查（防止并发冲突）
	if latestConn, latestExists := m.connMap[name]; latestExists {
		if latestConn.DeviceAddr == currentAddr && m.isConnValid(latestConn.Conn) {
			m.closeConnection(latestConn.Conn)
			m.logger.Printf("插件已存在有效连接（%s），关闭新连接", name)
			return
		}
		// 关闭旧连接
		m.closeConnection(latestConn.Conn)
	}

	// 保存新连接
	m.connMap[name] = newConn
	newConn.Meta = meta
	m.logger.Printf("插件连接成功: %s@%s（协议：%s v%s）",
		name, currentAddr, meta.ProtocolName, meta.ProtocolVersion)

	// 更新指标
	if m.metrics != nil {
		m.metrics.totalConnections.Add(1)
	}
}

// 判断是否需要新建连接
func (m *PluginManager) needNewConnection(exists bool, conn *PluginConn, currentAddr string) (bool, string) {
	if !exists {
		return true, "连接不存在"
	}
	if conn.DeviceAddr != currentAddr {
		return true, fmt.Sprintf("地址变更（旧：%s → 新：%s）", conn.DeviceAddr, currentAddr)
	}
	if !m.isConnValid(conn.Conn) {
		return true, fmt.Sprintf("连接无效（状态：%s）", conn.Conn.GetState())
	}
	if conn.FailedHeartbeats.Load() >= maxFailedHeartbeats {
		return true, fmt.Sprintf("连续%d次心跳失败", maxFailedHeartbeats)
	}
	return false, "连接正常"
}

// 带重试创建插件连接
func (m *PluginManager) createPluginConnectionWithRetry(name, addr string, maxRetries int) (*PluginConn, *plugin.PluginMeta, error) {
	var lastErr error
	for i := 0; i <= maxRetries; i++ {
		if i > 0 {
			// 指数退避重试（100ms → 200ms → 400ms...）
			backoff := time.Duration(math.Pow(2, float64(i))) * 100 * time.Millisecond
			m.logger.Printf("重试创建连接（%d/%d）: %s@%s，等待%v", i+1, maxRetries, name, addr, backoff)
			time.Sleep(backoff)
		}

		conn, meta, err := m.createPluginConnection(name, addr)
		if err == nil {
			return conn, meta, nil
		}
		lastErr = err
		m.logger.Printf("创建连接失败（%d/%d）: %v", i+1, maxRetries, err)
	}
	return nil, nil, fmt.Errorf("重试耗尽（%d次），最后错误: %w", maxRetries, lastErr)
}

// 创建插件连接（底层gRPC拨号+初始化）
func (m *PluginManager) createPluginConnection(name, addr string) (*PluginConn, *plugin.PluginMeta, error) {
	// 构建gRPC拨号选项
	opts := []grpc.DialOption{
		grpc.WithBlock(), // 阻塞直到连接建立
		grpc.WithDefaultCallOptions(
			grpc.MaxCallRecvMsgSize(1024 * 1024), // 1MB最大消息大小
		),
	}

	// 添加TLS配置
	if m.tlsConfig.Enabled {
		creds, err := credentials.NewClientTLSFromFile(m.tlsConfig.CertFile, m.tlsConfig.ServerName)
		if err != nil {
			return nil, nil, fmt.Errorf("加载TLS证书失败: %w", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))
	} else {
		opts = append(opts, grpc.WithInsecure())
		m.logger.Printf("警告：插件连接未启用TLS（%s@%s）", name, addr)
	}

	// gRPC拨号（带超时）
	dialCtx, dialCancel := context.WithTimeout(m.stopCtx, defaultDialTimeout)
	defer dialCancel()
	conn, err := grpc.DialContext(dialCtx, addr, opts...)
	if err != nil {
		return nil, nil, fmt.Errorf("gRPC拨号失败: %w", err)
	}

	// 初始化插件（调用Init接口）
	client := plugin.NewPluginServiceClient(conn)
	initCtx, initCancel := context.WithTimeout(m.stopCtx, defaultInitTimeout)
	defer initCancel()
	meta, err := client.Init(initCtx, &plugin.InitRequest{})
	if err != nil {
		_ = conn.Close() // 初始化失败，关闭连接
		return nil, nil, fmt.Errorf("插件初始化失败: %w", err)
	}

	// 验证插件名称一致性
	if meta.ProtocolName != name {
		_ = conn.Close()
		return nil, nil, fmt.Errorf("插件名称不匹配（配置：%s → 实际：%s）", name, meta.ProtocolName)
	}

	// 初始化连接对象
	nowMs := time.Now().UnixMilli()
	pluginConn := &PluginConn{
		Client:       client,
		Conn:         conn,
		ProtocolName: name,
		DeviceAddr:   addr,
	}
	pluginConn.LastActive.Store(nowMs)
	pluginConn.LastHeartbeat.Store(nowMs - m.heartbeatFreq.Milliseconds())     // 立即触发首次心跳
	pluginConn.LastHeartbeatSent.Store(nowMs - m.heartbeatFreq.Milliseconds()) // 记录最后发送时间

	return pluginConn, meta, nil
}

// 清理已禁用的插件连接
func (m *PluginManager) cleanupDisabledPlugins(enabledMap map[string]*model.DeviceAgreement) {
	// 读锁收集待删除列表
	m.mu.RLock()
	var toRemove []string
	for name := range m.connMap {
		if _, isEnabled := enabledMap[name]; !isEnabled {
			toRemove = append(toRemove, name)
		}
	}
	m.mu.RUnlock()

	if len(toRemove) == 0 {
		return
	}

	// 写锁批量删除
	m.mu.Lock()
	defer m.mu.Unlock()
	for _, name := range toRemove {
		if conn, exists := m.connMap[name]; exists {
			m.closeConnection(conn.Conn)
			delete(m.connMap, name)
			m.logger.Printf("已移除禁用插件: %s（地址：%s）", name, conn.DeviceAddr)
		}
	}
}

// 清理所有插件连接
func (m *PluginManager) cleanupAllConnections() {
	m.mu.Lock()
	defer m.mu.Unlock()
	for name, conn := range m.connMap {
		m.closeConnection(conn.Conn)
		delete(m.connMap, name)
		m.logger.Printf("已移除插件: %s", name)
	}
	if m.metrics != nil {
		m.metrics.activeConnections.Store(0)
	}
}

// 发送所有插件心跳（主动轮询核心逻辑）
func (m *PluginManager) sendHeartbeats() {
	m.logger.Println("开始执行主动心跳检查（轮询）")

	// 读锁收集心跳任务
	m.mu.RLock()
	var tasks []struct {
		name string
		conn *PluginConn
	}
	nowMs := time.Now().UnixMilli()
	freqMs := m.heartbeatFreq.Milliseconds()
	for name, conn := range m.connMap {
		// 按心跳频率判断是否需要发送
		if nowMs-conn.LastHeartbeatSent.Load() >= freqMs {
			tasks = append(tasks, struct {
				name string
				conn *PluginConn
			}{name, conn})
		}
	}
	m.mu.RUnlock()

	if len(tasks) == 0 {
		m.logger.Println("无需要发送心跳的插件")
		return
	}

	// 并发发送心跳（信号量控制）
	var wg sync.WaitGroup
	for _, task := range tasks {
		wg.Add(1)
		if err := m.heartbeatSem.Acquire(m.stopCtx, 1); err != nil {
			m.logger.Printf("获取心跳信号量失败（%s）: %v", task.name, err)
			wg.Done()
			continue
		}
		go func(name string, conn *PluginConn) {
			defer wg.Done()
			defer m.heartbeatSem.Release(1)
			m.sendPluginHeartbeat(name, conn)
		}(task.name, task.conn)
	}
	wg.Wait()
}

// 发送单个插件心跳
func (m *PluginManager) sendPluginHeartbeat(name string, conn *PluginConn) {
	// 检查连接有效性
	if !m.isConnValid(conn.Conn) {
		m.logger.Printf("插件连接无效，跳过心跳: %s", name)
		conn.FailedHeartbeats.Add(1)
		if m.metrics != nil {
			m.metrics.heartbeatFailures.Add(1)
		}
		return
	}

	// 记录发送时间（无论成功与否，只要发送了就算）
	now := time.Now().UnixMilli()
	conn.LastHeartbeatSent.Store(now)
	if m.metrics != nil {
		m.metrics.heartbeatSent.Add(1)
	}

	// 发送心跳请求（带超时）
	heartCtx, heartCancel := context.WithTimeout(m.stopCtx, defaultHeartbeatTimeout)
	defer heartCancel()
	req := &plugin.PingRequest{ClientTimestamp: now}
	resp, err := conn.Client.Ping(heartCtx, req)

	if err != nil {
		// 心跳发送成功但响应失败
		conn.FailedHeartbeats.Add(1)
		m.logger.Printf("插件心跳响应失败（已成功发送）: %s, 错误: %v, 连续失败：%d次",
			name, err, conn.FailedHeartbeats.Load())
		if m.metrics != nil {
			m.metrics.heartbeatFailures.Add(1)
		}
		return
	}

	// 心跳成功（发送并响应成功）
	conn.LastHeartbeat.Store(now)
	conn.FailedHeartbeats.Store(0)
	if !resp.IsHealthy {
		m.logger.Printf("插件状态异常（心跳发送接收成功）: %s, 状态: %s", name, resp.StatusInfo)
	} else {
		m.logger.Printf("插件心跳正常（发送接收成功）: %s, 状态: %s", name, resp.StatusInfo)
	}
	if m.metrics != nil {
		m.metrics.heartbeatSuccesses.Add(1)
	}
}

// 查询启用的插件
func (m *PluginManager) queryEnabledPlugins() ([]*model.DeviceAgreement, error) {
	queryCtx, queryCancel := context.WithTimeout(m.stopCtx, 5*time.Second)
	defer queryCancel()

	return query.DeviceAgreement.
		WithContext(queryCtx).
		Where(query.DeviceAgreement.Enable.Eq(1)).
		Find()
}

// 检查gRPC连接有效性
func (m *PluginManager) isConnValid(conn *grpc.ClientConn) bool {
	if conn == nil {
		return false
	}

	state := conn.GetState()
	// 处理Connecting状态：等待100ms后重试
	if state == connectivity.Connecting {
		conn.WaitForStateChange(context.Background(), state)
		state = conn.GetState()
	}

	return state == connectivity.Ready || state == connectivity.Idle
}

// 关闭gRPC连接（带超时）
func (m *PluginManager) closeConnection(conn *grpc.ClientConn) {
	if conn == nil {
		return
	}

	closeCtx, closeCancel := context.WithTimeout(context.Background(), defaultCloseTimeout)
	defer closeCancel()

	done := make(chan struct{})
	go func() {
		defer close(done)
		_ = conn.Close()
	}()

	select {
	case <-done:
		m.logger.Printf("连接关闭成功（状态：%s）", conn.GetState())
	case <-closeCtx.Done():
		m.logger.Printf("连接关闭超时: %v", closeCtx.Err())
	}
}

// ------------------------------ 对外业务接口 ------------------------------
// GetPlugin：通过名称获取插件客户端
func (m *PluginManager) GetPlugin(name string) (plugin.PluginServiceClient, bool) {
	// 第一次检查
	m.mu.RLock()
	conn, exists := m.connMap[name]
	m.mu.RUnlock()

	if !exists {
		return nil, false
	}

	// 检查连接有效性
	if !m.isConnValid(conn.Conn) {
		m.logger.Printf("插件连接无效: %s", name)
		return nil, false
	}

	// 检查心跳发送超时（只要成功发送就算，这里检查是否长时间未发送）
	nowMs := time.Now().UnixMilli()
	lastSentMs := conn.LastHeartbeatSent.Load()
	timeoutMs := int64(heartbeatSendTimeout) * m.heartbeatFreq.Milliseconds()

	if nowMs-lastSentMs > timeoutMs {
		m.logger.Printf("插件心跳发送超时: %s（超过%dms未发送心跳）",
			name, timeoutMs)
		return nil, false
	}

	// 检查连续心跳失败（即使发送成功但多次无响应也判定为无效）
	if conn.FailedHeartbeats.Load() >= maxFailedHeartbeats {
		m.logger.Printf("插件连续%d次心跳响应失败: %s", maxFailedHeartbeats, name)
		return nil, false
	}

	return conn.Client, true
}

// BuildRequest：构建插件请求数据
func (m *PluginManager) BuildRequest(pluginName, command string, params map[string]string) (*plugin.BuildRequestResponse, error) {
	client, exists := m.GetPlugin(pluginName)
	if !exists {
		return nil, fmt.Errorf("插件不存在或连接无效: %s", pluginName)
	}

	reqCtx, reqCancel := context.WithTimeout(m.stopCtx, defaultRequestTimeout)
	defer reqCancel()

	resp, err := client.BuildRequest(reqCtx, &plugin.BuildRequestRequest{
		Command: command,
		Params:  params,
	})

	// 更新指标
	if m.metrics != nil {
		if err == nil && resp.Success {
			m.metrics.requestSuccesses.Add(1)
		} else {
			m.metrics.requestFailures.Add(1)
		}
	}

	if err != nil {
		return nil, fmt.Errorf("构建请求失败: %w", err)
	}
	if !resp.Success {
		return resp, fmt.Errorf("插件返回失败: %s", resp.Error)
	}

	return resp, nil
}

// ParseResponse：解析插件响应数据
func (m *PluginManager) ParseResponse(pluginName string, data []byte, command string) (*plugin.ParseResponseResponse, error) {
	client, exists := m.GetPlugin(pluginName)
	if !exists {
		return nil, fmt.Errorf("插件不存在或连接无效: %s", pluginName)
	}

	reqCtx, reqCancel := context.WithTimeout(m.stopCtx, defaultRequestTimeout)
	defer reqCancel()

	resp, err := client.ParseResponse(reqCtx, &plugin.ParseResponseRequest{
		Data:    data,
		Command: command,
	})

	// 更新指标
	if m.metrics != nil {
		if err == nil && resp.Success {
			m.metrics.requestSuccesses.Add(1)
		} else {
			m.metrics.requestFailures.Add(1)
		}
	}

	if err != nil {
		return nil, fmt.Errorf("解析响应失败: %w", err)
	}
	if !resp.Success {
		return resp, fmt.Errorf("插件返回失败: %s", resp.Error)
	}

	return resp, nil
}

// GetSensorType：获取插件支持的传感器类型
func (m *PluginManager) GetSensorType(pluginName string) (*plugin.GetTypeResponse, error) {
	client, exists := m.GetPlugin(pluginName)
	if !exists {
		return nil, fmt.Errorf("插件不存在或连接无效: %s", pluginName)
	}

	reqCtx, reqCancel := context.WithTimeout(m.stopCtx, defaultRequestTimeout)
	defer reqCancel()

	return client.GetType(reqCtx, &plugin.GetTypeRequest{})
}

// GetSensorModel：获取插件支持的传感器模型
func (m *PluginManager) GetSensorModel(pluginName string) (*plugin.GetModelResponse, error) {
	client, exists := m.GetPlugin(pluginName)
	if !exists {
		return nil, fmt.Errorf("插件不存在或连接无效: %s", pluginName)
	}

	reqCtx, reqCancel := context.WithTimeout(m.stopCtx, defaultRequestTimeout)
	defer reqCancel()

	return client.GetModel(reqCtx, &plugin.GetModelRequest{})
}

// Status：获取管理器状态（含指标）
func (m *PluginManager) Status() map[string]interface{} {
	m.mu.RLock()
	defer m.mu.RUnlock()

	status := map[string]interface{}{
		"running":        m.running.Load(),
		"plugin_count":   len(m.connMap),
		"check_interval": m.checkInterval.String(),
		"heartbeat_freq": m.heartbeatFreq.String(),
		"concurrency":    map[string]int64{
			//"max_conn":  m.connSemaphore.MaxWeight(),
			//"max_heart": m.heartbeatSem.MaxWeight(),
		},
	}

	// 指标信息
	if m.metrics != nil {
		status["metrics"] = map[string]int64{
			"total_connections":   m.metrics.totalConnections.Load(),
			"active_connections":  m.metrics.activeConnections.Load(),
			"failed_connections":  m.metrics.failedConnections.Load(),
			"heartbeat_sent":      m.metrics.heartbeatSent.Load(),
			"heartbeat_successes": m.metrics.heartbeatSuccesses.Load(),
			"heartbeat_failures":  m.metrics.heartbeatFailures.Load(),
			"request_successes":   m.metrics.requestSuccesses.Load(),
			"request_failures":    m.metrics.requestFailures.Load(),
		}
	}

	return status
}

// Stop：优雅停止管理器
func (m *PluginManager) Stop() {
	if !m.running.CompareAndSwap(true, false) {
		m.logger.Println("插件管理器未运行，无需停止")
		return
	}

	m.logger.Println("开始停止插件管理器...")

	// 1. 触发停止信号
	m.stopCancel()

	// 2. 停止定时器
	m.ticker.Stop()

	// 3. 等待所有协程退出
	m.wg.Wait()

	// 4. 清理所有连接
	m.cleanupAllConnections()

	m.logger.Println("插件管理器已完全停止")
}

// ------------------------------ 全局单例 ------------------------------
var (
	globalManager *PluginManager
	initOnce      sync.Once
)

// InitGlobalManager：初始化全局插件管理器
func InitGlobalManager(opts Options) error {
	var err error
	initOnce.Do(func() {
		globalManager, err = NewPluginManager(opts)
		if err == nil {
			err = globalManager.Start()
		}
	})
	return err
}

// GetGlobalManager：获取全局插件管理器
func GetGlobalManager() (*PluginManager, error) {
	if globalManager == nil {
		return nil, errors.New("全局插件管理器未初始化，请先调用InitGlobalManager")
	}
	return globalManager, nil
}
